package com.streaminggbs.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.fastjson.JSON;
import com.streaminggbs.common.base.Video2CommonReturnBean;
import com.streaminggbs.entity.DeviceInfo;
import com.streaminggbs.entity.PhotoFile;
import com.streaminggbs.interfaces.*;
import com.streaminggbs.common.utils.*;
import com.streaminggbs.model.DeviceChannelModel;
import com.streaminggbs.model.DownloadProgressModel;
import com.streaminggbs.model.DownloadRecordModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.streaminggbs.common.base.ReturnBean;
import com.streaminggbs.common.job.StreamCheckJob;
import com.streaminggbs.service.WebSocketServerImpl;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;



@Api(tags = {"GB28181的接口数据"})
@RestController
@Slf4j
public class GB28181Controller {

    @Autowired
    Gb28181Service gb28181Service;
    @Autowired
    DeviceInfoService deviceInfoService;
    @Autowired
    WebSocketServerImpl webSocketServerImpl;
    @Autowired
    StreamCheckJob streamCheckJob;
    @Autowired
    RecordFileService recordFileService;
    @Autowired
    SysParamSetService sysParamSetService;


    @ApiOperation("视频发起")
    @RequestMapping(value = "/play", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> play(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            @ApiParam("0：音视频 1视频 2 双向对讲 3 监听 4 中心广播5 透传") @RequestParam("vedioType") Integer vedioType,
            @ApiParam("是否录像") @RequestParam(required = false, name = "record", defaultValue = "0") Integer record
    ) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        try {
            JSONObject jsonObject = new JSONObject();
            int isOnline = gb28181Service.online(device,channel);
            jsonObject.put("online",isOnline);
            if(isOnline==1) {
                gb28181Service.play(device, channel, vedioType, record, false,jsonObject);
            }
            return new ResponseEntity<>(new ReturnBean(jsonObject), HttpStatus.OK);
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("视频发起实时录像")
    @RequestMapping(value = "/start/video", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> startVideo(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel
    ) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        String sinkid = gb28181Service.startRealVideo(device,channel);
        return new ResponseEntity<>(new ReturnBean(0,"启动成功"), HttpStatus.OK);
    }

    @ApiOperation("视频发起实时录像停止")
    @RequestMapping(value = "/stop/video", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> stopVideo(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel
    ) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        String url = gb28181Service.stopRealVideo(device,channel);
            return new ResponseEntity<>(new ReturnBean(0,"成功!"), HttpStatus.OK);
    }

    @ApiOperation("视频控制")
    @RequestMapping(value = "/playControl", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<String> playControl(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            @ApiParam("0：关闭音视频传输1：切换码流（增加暂停和继续）2：暂停该通道所有流的发送3：恢复暂停流的发送，与暂停前流格式保持一致4：关闭双向对讲") @RequestParam("command") int command,
            @ApiParam("0：关闭该通道有关的音视频流1：只关闭该通道的音频保留视频2：只关闭该通道的视频保留音频") @RequestParam(required = false, name = "closeType", defaultValue = "0") int closeType,
            @ApiParam("0：主码流1：子码流") @RequestParam(required = false, name = "switchType", defaultValue = "0") int switchType

    ) {
        try {
            if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
                return ResponseEntity.notFound().build();
            }
            gb28181Service.playControl(device, channel, command, closeType, switchType, false);
            return ResponseEntity.ok("ok");
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("视频回放")
    @RequestMapping(value = "/playBack", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> playBack(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            @ApiParam("协议(TCP/UDP)") @RequestParam(required = false, name = "protocol", defaultValue = "TCP") String protocol,
            @ApiParam("开始时间yyyy-MM-dd hh:mm:ss") @RequestParam("startTime") String startTime,
            @ApiParam("结束时间yyyy-MM-dd hh:mm:ss") @RequestParam("endTime") String endTime
    ) {
        try {
            if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
                return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
            }
            startTime = startTime.replace("T", " ");
            endTime = endTime.replace("T", " ");

            JSONObject playBackModelJson =gb28181Service.playBack(device, channel, startTime, endTime);
			return new ResponseEntity<>(new ReturnBean(playBackModelJson), HttpStatus.OK);

        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("视频回放控制")
    @RequestMapping(value = "/playBackControl", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<String> playBackControl(
            @ApiParam("流id") @RequestParam(name = "streamid") String streamid,
            @ApiParam("play/pause/seek/scale(stop)") @RequestParam(name = "command") String command,
            @ApiParam("seek的索引，单位秒例npt=200") @RequestParam(required = false, name = "range") Integer range,
            @ApiParam("速度0.25/0.5/1/2/4") @RequestParam(required = false, name = "scale") Double scale
    ) {
        try {
            if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
                return ResponseEntity.notFound().build();
            }
            gb28181Service.playBackControl(streamid,command,range,scale);
            return ResponseEntity.ok("ok");
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }

    }

    @ApiOperation("历史视频下载请求")
    @RequestMapping(value = "/fileUpload", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> downLoadVideo(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            @ApiParam("开始时间yyyy-MM-dd'T'hh:mm:ss") @RequestParam("startTime") String startTime,
            @ApiParam("结束时间yyyy-MM-dd'T'hh:mm:ss") @RequestParam("endTime") String endTime,
            @ApiParam("录像下载速度") @RequestParam(required = false, name = "speed") Integer speed
    ) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        JSONObject downloadRecordModel = null;
        try {
            downloadRecordModel = gb28181Service.gb28181DownloadVideo(device,channel, startTime, endTime, speed);
            return new ResponseEntity<>(new ReturnBean(downloadRecordModel), HttpStatus.OK);
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("视频列表查看")
    @RequestMapping(value = "/queryVedioList", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<String> queryVedioList(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            //@ApiParam("0:设备  1：服务器 2 设备和服务器") @RequestParam(required = false, name ="memoryType") Integer memoryType,
            @ApiParam("0:设备  1：服务器 2 设备和服务器") @RequestParam(required = false, name ="storageType") Integer storageType,
            @ApiParam("开始时间yyyy-MM-dd hh:mm:ss") @RequestParam("startTime") String startTime,
            @ApiParam("结束时间yyyy-MM-dd hh:mm:ss") @RequestParam("endTime") String endTime
    ) {
//        if(storageType==null){
//            storageType = memoryType;
//        }
        JSONArray jsonArray = gb28181Service.queryVedioList(device,channel,storageType,startTime,endTime);
        return ResponseEntity.ok(jsonArray.toString());
    }

    @ApiOperation("设备重启")
    @RequestMapping(value = "/deviceReboot", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> stateQuery(
            @ApiParam("设备编号") @RequestParam("device") String device
    ) {
        try {
            return ResponseEntity.ok(Video2CommonReturnBean.convert(gb28181Service.deviceReboot(device)));
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("布防")
    @RequestMapping(value = "/alarmSetguard", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> alarmSet(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel
    ) {
        try {
            return ResponseEntity.ok(Video2CommonReturnBean.convert(gb28181Service.alarmSetguard(device,channel)));
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }
    @ApiOperation("取消布防")
    @RequestMapping(value = "/alarmResetguard", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> stateQuery(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel
    ) {
        try {
            return ResponseEntity.ok(Video2CommonReturnBean.convert(gb28181Service.alarmResetguard(device,channel)));
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }
    @ApiOperation("报警复位")
    @RequestMapping(value = "/alarmReset", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<ReturnBean> alarmReset(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel
    ) {
        try {
            return ResponseEntity.ok(Video2CommonReturnBean.convert(gb28181Service.alarmReset(device,channel)));
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("云台控制")
    @RequestMapping(value = "/yuntab", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<String> yuntab(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            @ApiParam("镜头变焦 0：镜头变焦无效 1: 变大 2：缩小") @RequestParam("zoom") int zoom,
            @ApiParam("光圈 0：光圈无效 1: 变大 2：缩小") @RequestParam("aperture") int aperture,
            @ApiParam("焦点 0：焦点无效 1: 变大 2：缩小") @RequestParam("focus") int focus,
            @ApiParam("0：水平方向移动无效 1：左2：右") @RequestParam("horizontal") int horizontal,
            @ApiParam("0：垂直方向移动无效 1：上2：下") @RequestParam("vertical") int vertical,
            @ApiParam("0-15 变焦的速度") @RequestParam(required = false, name = "zoom_level", defaultValue = "1") int zoomLevel,
            @ApiParam("0-255 水平方向移动速度") @RequestParam(required = false, name = "horizontal_level", defaultValue = "1") int horizontalLevel,
            @ApiParam("0-255 垂直方向移动速度") @RequestParam(required = false, name = "vertica_level", defaultValue = "1") int verticaLevel
    ) {
        try {
            gb28181Service.yuntab(device, channel, zoom, horizontal, vertical, zoomLevel, horizontalLevel, verticaLevel,focus);
            return ResponseEntity.ok("ok");
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation("获取视频录制相对时间戳")
    @RequestMapping(value = "/queryVideoRecordTime", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<String> queryVideoRecordTime(
            @ApiParam(value = "downloadId") @RequestParam(value = "downloadId", required = true) String downloadId
    ) {
        JSONObject json = new JSONObject();
        json.put("status", 1);
        try {
            DownloadProgressModel downloadProgressModel = gb28181Service.queryDownloadProgress(downloadId);
            if (null != downloadProgressModel ){
                if(downloadProgressModel.getStop()-downloadProgressModel.getStart()>0) {
                    Integer progressPercent = new BigDecimal(downloadProgressModel.getDuration()).divide(new BigDecimal((downloadProgressModel.getStop() - downloadProgressModel.getStart()) * 1000), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
                    log.info("获取的进度百分比的值:{},{}", progressPercent, JSON.toJSONString(downloadProgressModel));
                    json.put("percent", progressPercent);
                }else{
                    log.info("获取的进度百分比的值:{}",  JSON.toJSONString(downloadProgressModel));
                }
            }
            json.put("status", 0);
            return ResponseEntity.ok(json.toString());
        } catch (Exception e) {
            log.error("获取值异常:{}",e);
            return ResponseEntity.notFound().build();
        }
    }

    @ApiOperation(value = "在线设备订阅位置信息", notes = "在线设备订阅位置信息")
    @RequestMapping(value = "/subscribeAllLocation", method = RequestMethod.GET)
    public ResponseEntity<ReturnBean> subscribeAllLocation() {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<ReturnBean>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setStatus(1);
        deviceInfo.setSubscribeLocationFlag(Boolean.FALSE);
        List<DeviceInfo> list = deviceInfoService.select(deviceInfo);
        if (null != list && !list.isEmpty()) {
            for (DeviceInfo nowDeviceInfo : list) {
                boolean bol = gb28181Service.subscribeAllLocation(nowDeviceInfo.getDevice());
                if (bol) {
                    DeviceInfo updateDeviceInfo = new DeviceInfo();
                    updateDeviceInfo.setSubscribeLocationFlag(Boolean.TRUE);
                    updateDeviceInfo.setId(nowDeviceInfo.getId());
                    deviceInfoService.updateNotNull(updateDeviceInfo);
                }
            }
        }
        return new ResponseEntity<>(new ReturnBean(), HttpStatus.OK);
    }

    @ApiOperation(value = "单个设备订阅位置信息", notes = "单个设备订阅位置信息")
    @RequestMapping(value = "/subscribeLocationByDeviceId/{id}", method = RequestMethod.GET)
    public ResponseEntity<ReturnBean> subscribeLocationByDeviceId(@PathVariable("id") String id) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<ReturnBean>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        DeviceInfo deviceInfo = deviceInfoService.selectByKey(id);
        if (null != deviceInfo && deviceInfo.getSubscribeLocationFlag().equals(Boolean.FALSE)) {
            boolean bol = gb28181Service.subscribeAllLocation(deviceInfo.getDevice());
            if (bol) {
                DeviceInfo updateDeviceInfo = new DeviceInfo();
                updateDeviceInfo.setSubscribeLocationFlag(Boolean.TRUE);
                updateDeviceInfo.setId(deviceInfo.getId());
                deviceInfoService.updateNotNull(updateDeviceInfo);
            }
        }
        return new ResponseEntity<>(new ReturnBean(), HttpStatus.OK);
    }

    @ApiOperation(value = "设备-对讲", notes = "设备-对讲")
    @RequestMapping(value = "/startSpeak/{device}", method = RequestMethod.GET)
    public ResponseEntity<ReturnBean> startSpeak(@PathVariable("device") String device) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        JSONObject jsonObject = gb28181Service.startSpeak(device);
        return new ResponseEntity<>(new ReturnBean(jsonObject), HttpStatus.OK);
    }

    @ApiOperation(value = "设备-广播", notes = "设备-对讲")
    @RequestMapping(value = "/broadcast", method = RequestMethod.POST)
    public ResponseEntity<ReturnBean> broadcast(
            @ApiParam("设备编号") @RequestParam("device") String device,
            @ApiParam("摄像头编号") @RequestParam("channel") String channel,
            @ApiParam("对讲接口返回的stream") @RequestParam(required = true, name = "source") String source,
            @ApiParam("0：TCP广播，不带包长；1：TCP广播，带2字节包长；2：UDP广播;") @RequestParam(required = false, name = "mode", defaultValue = "1") Integer mode
    ) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        JSONObject jsonObject = gb28181Service.broadcast(device,channel,source,mode);
        return new ResponseEntity<>(new ReturnBean(jsonObject), HttpStatus.OK);
    }


    @ApiOperation(value = "获取设备通道信息", notes = "获取设备通道信息")
    @RequestMapping(value = "/getDeviceChannel/{device}", method = RequestMethod.GET)
    public ResponseEntity<ReturnBean> getDeviceChannel(@PathVariable("device")String device) {
        if (StringUtils.isEmpty(sysParamSetService.pick().getVideoServerUrl())) {
            return new ResponseEntity<>(new ReturnBean(-1,"请先配置视频服务器的请求地址!"), HttpStatus.OK);
        }
        JSONObject jsonObject = gb28181Service.getDeviceChannel(device);
        if (jsonObject.getIntValue("code") != 200) {
            return new ResponseEntity<>(new ReturnBean(-1, jsonObject.getString("msg")), HttpStatus.OK);
        }
        return new ResponseEntity<>(new ReturnBean(jsonObject.getJSONArray("ChannelList").toJavaList(DeviceChannelModel.class)), HttpStatus.OK);
    }

}
